﻿using System;
using System.Reactive.Linq;
using ZOIL.Framework.Presentation;
using System.Windows;

namespace ZOIL.Library.Behaviors
{
    public class SynchronizeViewportPluginBehavior : PluginBehavior<ZInformationLandscape, SynchronizeViewportBehavior>
    {
        #region private fields

        private IDisposable _landscapeChangedSubscription;

        #endregion

        #region overrides

        protected override void OnParentBehaviorChangedImpl(object oldParentBehavior, object newParentBehavior)
        {
            SenderID = ParentBehavior.SenderID;

            CreateOneWayParentBehaviorBinding(SynchronizeViewportBehavior.TypeProperty, TypeProperty);
            CreateOneWayParentBehaviorBinding(SynchronizeViewportBehavior.SenderIDProperty, SenderIDProperty);
        }

        protected override void OnAttached()
        {
            _landscapeChangedSubscription = RegisterLandscapeChangedEvent();
        }

        protected override void OnDetaching()
        {
            if (_landscapeChangedSubscription != null)
                _landscapeChangedSubscription.Dispose();
        }

        #endregion

        #region private methods

        private IDisposable RegisterLandscapeChangedEvent()
        {
            var landscapeChanged = Observable.FromEventPattern<ZLandscapeAnimationEventArgs>(AssociatedObject, "AnimationChanged").Select(evt => AssociatedObject);
            return landscapeChanged.Subscribe(OnViewportChanged);
        }

        #endregion

        #region dependency properties

        #region Type

        public CommunicationType Type
        {
            get { return (CommunicationType)GetValue(TypeProperty); }
            set { SetValue(TypeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Type.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TypeProperty =
            DependencyProperty.Register("Type", typeof(CommunicationType), typeof(SynchronizeViewportPluginBehavior), new PropertyMetadata(CommunicationType.Both, OnTypeChanged));

        /// <summary>
        /// Handles changes to the Type property.
        /// </summary>
        private static void OnTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var target = (SynchronizeViewportPluginBehavior)d;
            var oldType = (CommunicationType)e.OldValue;
            var newType = target.Type;
            target.OnTypeChanged(oldType, newType);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the Type property.
        /// </summary>
        protected virtual void OnTypeChanged(CommunicationType oldType, CommunicationType newType)
        {
        }

        #endregion

        #region SenderID

        /// <summary>
        /// SenderID Dependency Property
        /// </summary>
        public static readonly DependencyProperty SenderIDProperty =
            DependencyProperty.Register("SenderID", typeof(string), typeof(SynchronizeViewportPluginBehavior),
                new FrameworkPropertyMetadata(null, OnSenderIDChanged));

        /// <summary>
        /// Gets or sets the SenderID property. This dependency property 
        /// indicates ....
        /// </summary>
        public string SenderID
        {
            get { return (string)GetValue(SenderIDProperty); }
            set { SetValue(SenderIDProperty, value); }
        }

        /// <summary>
        /// Handles changes to the SenderID property.
        /// </summary>
        private static void OnSenderIDChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var target = (SynchronizeViewportPluginBehavior)d;
            var oldSenderID = (string)e.OldValue;
            var newSenderID = target.SenderID;
            target.OnSenderIDChanged(oldSenderID, newSenderID);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the SenderID property.
        /// </summary>
        protected virtual void OnSenderIDChanged(string oldSenderID, string newSenderID)
        {
        }

        #endregion

        #endregion

        #region virtual methods

        protected virtual void OnViewportChanged(ZInformationLandscape landscape)
        {
        }

        #endregion

        #region Viewport Handling

        protected void ViewportReceived(Viewport viewport)
        {
            ParentBehavior.RaiseViewportReceivedEvent(viewport);
        }

        #endregion
    }
}
